home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d18 / tjtot10a.arc / DOCS.EXE / arc / CHAPT12.TXT < prev    next >
Text File  |  1991-05-19  |  59KB  |  1,430 lines

  1.                                                                            Menus
  2.                                                                            Menus
  3.                                                                            Menus
  4.  
  5.  
  6.  
  7.          "Ninety-eight percent of the adults in this country are decent, hard-
  8.          working Americans. It's the other lousy two percent that get all the
  9.          publicity. But then we elected them."
  10.  
  11.                                                                      Lily Tomlin
  12.  
  13.  
  14.  
  15.  
  16.  
  17. Introduction
  18.          You want menus, we got menus!
  19.  
  20.          The Toolkit includes three main menu types: pop-up menus, Lotus-style
  21.          menu bars and pull-down menus. All the menus can be nested many levels
  22.          deep, i.e. when the user selects an item from a menu, another menu can
  23.          be automatically displayed. You may optionally specify a description
  24.          for any menu item, and when the user highlights the item, the descrip-
  25.          tive text is automatically displayed. All the menus provide full mouse
  26.          support, and if the mouse cursor drifts across a specific item, it is
  27.          automatically highlighted. Menu items can also be selected with the
  28.          cursor keys or by pressing a menu item hotkey.
  29.          The object hierarchy includes a number of abstract objects, as illus-
  30.          trated in figure 12.1. You should never declare an instance of type
  31.          BaseMenuOBJ, WinMenuOBJ, BarMenuOBJ or KwikPullOBJ, as these are
  32.          abstract. Use one of the following objects to display a menu:
  33.  
  34.          MenuOBJ            This object displays a simple menu in a window. This
  35.                             object is commonly used for a program's main menu
  36.                             which is displayed when the program starts.
  37.          MoveMenuOBJ        This object is similar to MenuOBJ, except that the
  38.                             user can drag the menu around the screen to view the
  39.                             contents of the screen below.
  40.  
  41.          LotusMenuOBJ       The LotusMenuOBJ provides a 1-2-3 (or Paradox!)
  42.                             style menu bar. The user scrolls left and right
  43.                             along the menu bar.
  44.          PullMenuOBJ        This is an "IDE-like" pull-down menu which supports
  45.                             multiple levels of sub-menus.
  46.  
  47.          EZPullArrayOBJ     This objects provides a quick and easy way of
  48.                             creating a sophisticated pull-down menu. All you
  49.                             have to do is update a string array with the
  50.                             individual item details, and instruct the Toolkit to
  51.                             display the menu.
  52.  
  53. 12-2                                                                User's Guide
  54. --------------------------------------------------------------------------------
  55.  
  56.          EZPullLinkOBJ      This object is similar to the EZPullArrayOBJ, except
  57.                             that the menu item details are added to a linked
  58.                             list (of type DLLOBJ or descendant).
  59.  
  60.  
  61. Figure 12.1                                                            [PICTURE]
  62. Menu
  63. Object Hierarchy
  64.  
  65.  
  66.  
  67. Common Methods
  68.          All menus contain items, hotkeys, descriptions, and the like. The Tool-
  69.          kit's varied menu objects share a variety of common methods which are
  70.          used to construct the menu details and characteristics.
  71.  
  72.  
  73. Adding Menu Item Details
  74.  
  75.          The following methods are used to set the individual menu details:
  76.  
  77.          Init;
  78.  
  79.          The Init method is passed no parameters, and should be called before
  80.          any other menu method.
  81.  
  82.          AddItem(Txt:StrVisible);
  83.  
  84.          This method is used to add an item to the menu. The method is passed
  85.          one parameter identifying the menu text to be displayed. The item
  86.          string may include embedded highlight characters to indicate that a
  87.          specific character is designated as a hot key -- refer to the WriteHi
  88.          method on page 5-3 for further information. Special strings can be
  89.          passed to force blanks or lines in the menu item list - see the note at
  90.          the end of this section.
  91.  
  92.          The following methods may be called to further define the settings for
  93.          each item. Note, however, that the item must have been added with AddI-
  94.          tem (or AddFullItem) before these additional settings can be specified.
  95.  
  96.  
  97.          SetHK(Item:byte; HK:word);
  98.          Any item can be assigned a hotkey, which provides a way for the user to
  99.          select the item without scrolling to the item. All the user does is
  100.          press the hotkey. The de facto standard is to use normal alphabet char-
  101.          acters as the hotkeys. (Lotus and pull-down menus support additional
  102.          hotkeys which can be pressed even when the appropriate menu is not on
  103.          display -- this subject is discussed in detail later).
  104.  
  105.  
  106. Menus Menus Menus                                                           12-3
  107. --------------------------------------------------------------------------------
  108.  
  109.          SetMessage(Item:byte; Msg:StrVisible);
  110.  
  111.          The SetMessage method is used to define a message for an item. When the
  112.          item is highlighted, the message will be automatically displayed, and
  113.          when the user moves to a different item, the message is removed. The
  114.          Toolkit does not save the contents of the screen where the message is
  115.          displayed.
  116.  
  117.          SetID(Item:byte; ID:word);
  118.  
  119.          In a menu system, which includes sub-menus, this method can be used to
  120.          assign each topic in the menu a unique ID. The method is passed two
  121.          parameters; the item number and the item ID. This ID is of type word,
  122.          and will be returned by the menu method Activate if the item is
  123.          selected by the user. Note that you should not use IDs greater than
  124.          65000, because some of these IDs are used internally by the Toolkit.
  125.  
  126.          SetStatus(Item:byte, On:boolean);
  127.  
  128.          Sometimes, certain menu items will not be selectable. For example, a
  129.          File Save option may not be operative until a file has been loaded or
  130.          created. The SetStatus method is used to control whether an option is
  131.          selectable. The method is passed two parameters; the item number and a
  132.          boolean parameter. Set the boolean to TRUE to enable the item and FALSE
  133.          to disable it.
  134.  
  135.          SetSubMenu(Item:byte; SubMenu:BaseMenuPtr);
  136.  
  137.          This method is used to indicate that another menu should be displayed,
  138.          if the item is selected by the user. The Toolkit will automatically
  139.          display the new menu below and to the right of the active menu. The
  140.          method is passed two parameters; the item number and the address of the
  141.          sub-menu object. Normally, you will call another menu instance of the
  142.          same type as the parent, e.g. if the parent menu is of type MenuOBJ,
  143.          then the sub-menu is usually of type MenuOBJ. This, however, is not
  144.          mandatory, and any menu item can display a sub-menu of any type in the
  145.          menu object hierarchy. Note that the second parameter is the address of
  146.          the sub-menu, and is normally specified by preceding the menu object
  147.          with the Turbo Pascal "@" address symbol. For example:
  148.  
  149.                      SetSubMenu(5,@FileMenu);
  150.  
  151.          When you want to specify all the menu item details, e.g. message, HK,
  152.          sub-menu, etc., you can use the following all-in-one method:
  153.  
  154.  
  155.          AddFullItem(Txt:StrVisible;ID,Hk:word; Msg:StrVisible; SubM:Baseme-
  156.          nuPtr);
  157.  
  158.  
  159.  
  160. 12-4                                                                User's Guide
  161. --------------------------------------------------------------------------------
  162.  
  163.          As you may have guessed, this method is used to add a new item and
  164.          specify its settings in one heavy statement! This method is a single
  165.          replacement for five of the previous six methods. The only method that
  166.          is not accommodated by AddFullItem is SetStatus, and the Status is set
  167.          to true by default. Use one of the following values to suppress the
  168.          setting of one or more of the item elements:
  169.  
  170.               No ID                  0
  171.               No hotkey              0
  172.               No message             ''
  173.               No sub-menu            nil
  174.  
  175.          Listed below are two code fragments, both of which define the same
  176.          three-item menu. The first code block uses the individual methods, and
  177.          the second block takes advantage of AddFullItem. It doesn't matter
  178.          which technique you use, so use the one which seems easiest to you.
  179.          with MainMenu do
  180.          begin
  181.             Init;
  182.             AddItem(' ~L~oad file ')
  183.             SetID(1,1);
  184.             SetHK(1,76);
  185.             SetMessage(1,'Load a database file from disk');
  186.             AddItem(' ~S~ave file ');
  187.             SetID(2,2);
  188.             SetHK(83);
  189.             SetMessage(2,'Save the current database to disk');
  190.             AddItem(' ~Q~uit ');
  191.             SetID(3,99);
  192.             SetHK(3,81);
  193.             Setmessage(3,'Let''s party!');
  194.             ...
  195.          end;
  196.  
  197.  
  198.          with MainMenu do
  199.          begin
  200.             Init;
  201.             AddFullItem(' ~L~oad file ',1,76,'Load a database file from disk',-
  202.          nil);
  203.             AddFullItem(' ~S~ave file ',2,83,'Save the current database to
  204.          disk',nil);
  205.             AddFullItem(' ~Q~uit ',99,81,'Let''s party!',nil);
  206.             ...
  207.          end;
  208.  
  209.          Having created a menu, the following methods can be used to display,
  210.          start, remove and dispose of the menu.
  211.  
  212.  
  213.  
  214. Menus Menus Menus                                                           12-5
  215. --------------------------------------------------------------------------------
  216.  
  217.          Draw;
  218.  
  219.          This method instructs the object to draw itself. As soon as the menu is
  220.          drawn, the method returns control back to your program, i.e. the object
  221.          does not process any user input.
  222.  
  223.          Activate: word;
  224.  
  225.          This is the main "DO-IT!" method. If the menu is not already visible,
  226.          the menu is drawn, and then the Toolkit processes user input until the
  227.          user selects a menu item or ESCapes (if ESC is enabled). The function
  228.          method returns the ID of the selected item. If the ID was never speci-
  229.          fied, i.e. it is set to zero, the Toolkit will return the actual item
  230.          number. Note, however, that this number is the item number in the
  231.          currently displayed menu. In a system with sub-menus you will not know
  232.          which sub-menu was on display. In a system with sub-menus, you should
  233.          therefore always assign a unique ID to each selectable item. A zero is
  234.          returned if the user escaped.
  235.  
  236.          Remove;
  237.  
  238.          This methods removes the menu. If the menu is of type MenuOBJ or Move-
  239.          MenuOBJ, the underlying screen contents are restored. All other menu
  240.          objects do not restore any underlying screen contents -- they simply
  241.          erase the menu text.
  242.  
  243.          Done;
  244.  
  245.          When the menu is no longer required, call this method to dispose of the
  246.          memory used internally by the menu.
  247.  
  248.  
  249.  
  250. Changing Menu Characteristics
  251.  
  252.          The following methods are used to control the general display charac-
  253.          teristics of the menu:
  254.  
  255.          SetGap(G:byte);
  256.  
  257.          This method is used to create a space (or gap) to the left and right of
  258.          each menu item. In a pop-up menu, this can be used to create a space
  259.          between the menu border and the menu text. With Lotus and pull-down
  260.          menus, this method creates a space between each item along the top menu
  261.          bar. The method is passed one parameter; a byte representing the number
  262.          of characters space to allow on either side of each menu item.
  263.  
  264.          SetMenuXY(X,Y: byte);
  265.  
  266.  
  267.  
  268. 12-6                                                                User's Guide
  269. --------------------------------------------------------------------------------
  270.  
  271.          This method is used to set the specific location of the menu on the
  272.          screen. The method is passed two byte parameters representing the (X,Y)
  273.          coordinate of the top left corner of the menu. With pop-up menus, the
  274.          menu will be centered laterally and vertically if the X or Y parameter
  275.          is set to zero.
  276.  
  277.  
  278.          SetMesssageXY(X,Y:byte);
  279.          This method is used to specify the location of the optional message
  280.          which is displayed when a topic is highlighted. The method is passed
  281.          two parameters representing the (X,Y) coordinate of the first character
  282.          in the message.
  283.  
  284.  
  285.          SetAllowEsc(On:boolean);
  286.          This method is used to control whether the user may escape from the
  287.          menu. It is passed a single boolean parameter, which should be set to
  288.          TRUE to enable escape (the default), or FALSE to disable it.
  289.  
  290.  
  291.          SetActiveItem(Item:byte);
  292.          Normally, the first item in a menu is highlighted when the menu is
  293.          first displayed. If this item is non-selectable, or if you want to
  294.          highlight a different item, use the method SetActiveItem. The method is
  295.          passed one byte parameter identifying the topic number of the item to
  296.          be highlighted.
  297.  
  298.  
  299.          The display colors are controlled by the menu item colors, and (in the
  300.          case of pop-up and pull-down menus) the window display colors. All the
  301.          colors default to values established by LookTOT. To change the look and
  302.          feel of your menus, you should assign new default values to LookTOT.
  303.          Refer to page 3-12 for a description of how to control the LookTOT
  304.          defaults. The following two methods can be used to control the display
  305.          colors of any individual menu:
  306.  
  307.          SetColors(HiHot,HoNorm,LoHot,LoNorm,Off:byte);
  308.  
  309.          This method changes the display colors of the individual menu items.
  310.          The procedure is passed five byte parameters: the first two parameters
  311.          control the display color of the menu highlight bar -- the first param-
  312.          eter is the attribute of any highlighted text, e.g. the 'Q' in
  313.          '~Q~uit', and the second parameter is the standard display color, e.g.
  314.          the 'uit' part. The third and fourth parameters are the display attrib-
  315.          utes for the un-selected (or normal) menu items, and the fifth parame-
  316.          ter is the display attribute of inactive items. Note that this method
  317.          automatically sets the window body display color to the parameter
  318.          LoNorm.
  319.  
  320.  
  321.  
  322. Menus Menus Menus                                                           12-7
  323. --------------------------------------------------------------------------------
  324.  
  325.          Win^.SetColors(Border,Body,Title,Icons: byte);
  326.  
  327.          In the case of pop-up and pull-down menus, this method sets the colors
  328.          of the underlying window. Refer to page 7-6 for a general description
  329.          of this window method.
  330.  
  331.  
  332. Adding Lines and Gaps
  333.          Sometimes, you may want to display a menu with some items separated
  334.          from others. By specifying special item text, you instruct the Toolkit
  335.          to draw special lines, or leave a gap. The following item text should
  336.          be used:
  337.  
  338.          ''    A null string creates a gap in the menu.
  339.          '-'   A string comprising entirely of the minus sign will result in a
  340.                single horizontal line being drawn from the left to the right of
  341.                the menu.
  342.  
  343.          '='   A string comprising entirely of the equals sign will result in a
  344.                double horizontal line being drawn from the left to the right of
  345.                the menu.
  346.          For example, the following code fragment will force a blank line
  347.          between the third and fourth selectable items, and draws a single line
  348.          between the last two picks:
  349.  
  350.                   AddItem('Whips');
  351.                   AddItem('Chains');
  352.                   Additem('Rubber');
  353.                   AddItem('');
  354.                   AddItem('Hard Disks');
  355.                   AddItem('Floppies');
  356.                   AddItem('-');
  357.                   AddItem('Quit');
  358.  
  359.  
  360.  
  361.            Note: even non-selectable menu items are recognized as items in
  362.            the menu list. When you use one of the Set methods (described
  363.            earlier), be sure to include the non-selectable items in the list.
  364.            For example, in the above code fragment, the "Quit" item is item
  365.            number 8 (not 6), and its hotkey could be set to "Q" with the
  366.            following method call:
  367.  
  368.                               SetHK(8,ord('Q'));
  369.  
  370.  
  371.  
  372. 12-8                                                                User's Guide
  373. --------------------------------------------------------------------------------
  374.  
  375. Examples
  376.  
  377.          Listed below is the demo file DEMMN1.PAS, which illustrates how to
  378.          create a simple menu using some of the methods already described. Fig-
  379.          ure 12.2 illustrates the resultant display.
  380.          program DemoMenuOne;
  381.          {DEMMN1 - a basic menu}
  382.  
  383.          USES  DOS, CRT,
  384.                totMENU, totFAST;
  385.          var
  386.            Main: MenuOBJ;
  387.            Choice: byte;
  388.          begin
  389.             Screen.Clear(white,'░'); {paint the screen}
  390.             with Main do
  391.             begin
  392.                Init;
  393.                AddItem('');
  394.                AddItem(' Load a file          ');
  395.                AddItem(' Edit Date            ');
  396.                AddItem(' Save the file        ');
  397.                AddItem(' Change configuration ');
  398.                AddItem('-');
  399.                AddItem(' Quit                 ');
  400.                SetStyleTitle(1,' Main Menu ');
  401.                SetActiveItem(2);
  402.                Choice := Activate;
  403.                Done;
  404.             end;
  405.             if Choice = 0 then
  406.                Writeln('You escaped')
  407.             else
  408.                Writeln('You selected menu item ',Choice);
  409.          end.
  410.  
  411.  
  412. Figure 12.2                                                             [SCREEN]
  413. A Simple Menu
  414.  
  415.  
  416. Creating Pop-Up Menus
  417.  
  418.          totMENU provides two objects for creating pop-up menus: MenuOBJ and
  419.          MoveMenuOBJ. Both these objects create menus which are displayed in a
  420.          window, the only difference being that MoveMenuOBJ creates moveable
  421.          menus, i.e. menus that the user can drag around the screen.
  422.  
  423.  
  424.  
  425. Menus Menus Menus                                                           12-9
  426. --------------------------------------------------------------------------------
  427.  
  428.          Both objects are descendant from BaseMenuOBJ and inherit the following,
  429.          previously described, methods:
  430.  
  431.          Init;
  432.          AddItem(Txt:StrVisible);
  433.          SetHK(Item:byte; HK:word);
  434.          SetMessage(Item:byte; Msg:StrVisible);
  435.          SetID(Item:byte; ID:word);
  436.          SetStatus(Item:byte, On:boolean);
  437.          SetSubMenu(Item:byte; SubMenu:BaseMenuPtr);
  438.          AddFullItem(Txt:StrVisible;ID,Hk:word; Msg:StrVisible; SubM:Baseme-
  439.          nuPtr);
  440.          Draw;
  441.          Activate: word;
  442.          Remove;
  443.          SetGap(G:byte);
  444.          SetMenuXY(X,Y: byte);
  445.          SetMessageXY(X,Y:byte);
  446.          SetAllowEsc(On:boolean);
  447.          SetActiveItem(Item:byte);
  448.          SetColors(HiHot,HoNorm,LoHot,LoNorm,Off:byte);
  449.          Done;
  450.  
  451.          The menu is drawn on a window, and the following function methods can
  452.          be used to called any of the window methods:
  453.  
  454.  
  455.          Win: WinPtr;
  456.          Win: MoveWinPtr;
  457.          This function returns a pointer to the menu on which the menu is drawn.
  458.          For MenuOBJ instances the method returns a pointer to WinOBJ, and for
  459.          MoveWinOBJ it returns a pointer to MoveWinOBJ. Using the syntax
  460.          Win^.method you may call any of the window methods.
  461.  
  462.  
  463.          The menu window dimensions are automatically calculated from the width
  464.          and number of menu items. You should therefore avoid calling the window
  465.          method SetSize. As a convenience, the following method provides an easy
  466.          way to change the menu style and title.
  467.  
  468.          SetStyleTitle(Style:byte; Tit:StrVisible);
  469.  
  470.          This method sets the style and title of the menu window. The style
  471.          parameter is the same as the box style parameter discussed on page 5-7,
  472.          and the title supports the special title characters discussed on page
  473.          5-8.
  474.  
  475.  
  476.  
  477. 12-10                                                               User's Guide
  478. --------------------------------------------------------------------------------
  479.  
  480.          The first example shown at the end of the previous section illustrated
  481.          how to create a MenuOBJ menu. The on-disk demo file DEMMN2.PAS shows
  482.          how to create a moveable menu and control the display colors. Listed
  483.          below is the demo file DEMMN3.PAS, which illustrates how to create a
  484.          nested menu system. Figure 12.3 shows the generated menu.
  485.  
  486.          program DemoMenuThree;
  487.          {DEMMN3 - nested pop-up menus}
  488.          USES  DOS, CRT,
  489.                totMENU, totFAST, totLOOK, totSYS;
  490.  
  491.          var
  492.            Main,
  493.            Load: MenuOBJ;
  494.            Choice: byte;
  495.          begin
  496.             Screen.PartClear(1,1,80,24,white,'░'); {paint the screen}
  497.             Screen.PartClear(1,24,80,25,30,' ');
  498.             with Load do
  499.             begin
  500.                Init;
  501.                AddItem('');
  502.                AddFullItem(' ~1~  Accounts Payable    ',11,49,
  503.                            'Load database ACTP1',nil);
  504.                AddFullItem(' ~2~  Accounts Receivable ',12,50,
  505.                            'Load database ACTR7',nil);
  506.                AddFullItem(' ~3~  Net Assets Employed ',13,51,
  507.                            'Load the ledger file',nil);
  508.                AddFullItem(' ~4~  Net Cash Flow       ',14,52,
  509.                            'Load the cash file',nil);
  510.                SetStyleTitle(6,'Load Menu');
  511.                SetActiveItem(2);
  512.                SetMessageXY(25,25);
  513.                SetGap(1);
  514.                Win^.SetClose(False);
  515.             end;
  516.             with Main do
  517.             begin
  518.                Init;
  519.                AddItem('');
  520.                AddFullItem(' ~1~   Load a file         ',1,49,
  521.                            'Loads a new database file',@Load);
  522.                AddFullItem(' ~2~   Edit Date            ',2,50,
  523.                            'Full screen editing of data base entries',nil);
  524.                AddFullItem(' ~3~   Save the file        ',3,51,
  525.                            'Save database file to disk',nil);
  526.                AddFullItem(' ~4~   Change configuration ',4,52,
  527.                            'Modify colors and defaults',nil);
  528.  
  529.  
  530.  
  531. Menus Menus Menus                                                          12-11
  532. --------------------------------------------------------------------------------
  533.  
  534.                AddItem('');
  535.                AddFullItem(' ~Q~   Quit                 ',99,81,
  536.                            'Exit system and return to DOS',nil);
  537.                SetStyleTitle(6,'Main Menu');
  538.                SetActiveItem(2);
  539.                SetMenuXY(0,4);
  540.                SetMessageXY(25,25);
  541.                SetGap(1);
  542.                Win^.SetClose(False);
  543.                Choice := Activate;
  544.                Done;
  545.                Load.Done;
  546.             end;
  547.             if Choice = 0 then
  548.                Writeln('You escaped')
  549.             else
  550.                Writeln('You selected menu item ',Choice);
  551.          end.
  552.  
  553.  
  554. Figure 12.3                                                             [SCREEN]
  555. Nested Pop-Up
  556. Menus
  557.  
  558.  
  559. Creating Lotus-style Menus
  560.  
  561.          Lotus-style menus are menu bars which occupy a single line, and the
  562.          user scrolls left and right through the items. An optional description
  563.          of the highlighted item is usually displayed on the line immediately
  564.          below the menu bar.
  565.          The LotusMenuOBJ object makes building Lotus-style menus easy. LotusMe-
  566.          nuOBJ is descendant from BaseMenuOBJ, and inherits the following, pre-
  567.          viously described, methods:
  568.  
  569.          Init;
  570.          AddItem(Txt:StrVisible);
  571.          SetHK(Item:byte; HK:word);
  572.          SetMessage(Item:byte; Msg:StrVisible);
  573.          SetID(Item:byte; ID:word);
  574.          SetStatus(Item:byte, On:boolean);
  575.          SetSubMenu(Item:byte; SubMenu:BaseMenuPtr);
  576.          AddFullItem(Txt:StrVisible;ID,Hk:word; Msg:StrVisible; SubM:Baseme-
  577.          nuPtr);
  578.          Draw;
  579.          Activate: word;
  580.          Remove;
  581.          SetGap(G:byte);
  582.          SetMenuXY(X,Y: byte);
  583.  
  584.  
  585. 12-12                                                               User's Guide
  586. --------------------------------------------------------------------------------
  587.  
  588.          SetMessageXY(X,Y:byte);
  589.          SetAllowEsc(On:boolean);
  590.          SetActiveItem(Item:byte);
  591.          SetColors(HiHot,HoNorm,LoHot,LoNorm,Off:byte);
  592.          Done;
  593.  
  594.  
  595.          Listed below are the contents of the file DEMMN4.PAS, which uses these
  596.          basic methods to build a simple single-level Lotus menu. Figure 12.4
  597.          shows the resultant menu display.
  598.          program DemoMenuFour;
  599.          {DEMMN1 - a simple lotus menu}
  600.  
  601.          USES  DOS, CRT,
  602.                totMENU, totFAST;
  603.          var
  604.            P: LotusMenuOBJ;
  605.            Choice: byte;
  606.          begin
  607.             Screen.Clear(white,'░'); {paint the screen}
  608.             with P do
  609.             begin
  610.                Init;
  611.                AddItem('Worksheet');
  612.                AddItem('Range');
  613.                AddItem('Copy');
  614.                AddItem('Move');
  615.                AddItem('File');
  616.                AddItem('Print');
  617.                AddItem('Graph');
  618.                AddItem('Data');
  619.                AddItem('System');
  620.                AddItem('Quit');
  621.                SetActiveItem(1);
  622.                SetGap(1);
  623.                Choice := Activate;
  624.                Done;
  625.             end;
  626.             GotoXY(1,5);
  627.             if Choice = 0 then
  628.                Writeln('You escaped')
  629.             else
  630.                Writeln('You selected menu item ',Choice);
  631.          end.
  632.  
  633.  
  634. Figure 12.4                                                             [SCREEN]
  635. A Simple Lotus
  636. Menu
  637.  
  638.  
  639. Menus Menus Menus                                                          12-13
  640. --------------------------------------------------------------------------------
  641.  
  642.          If the user is using a mouse to select an item, the item is selected
  643.          when the user lets go of the mouse button. If the user holds down the
  644.          mouse button, and drifts away from the menu surface, none of the items
  645.          will be highlighted. If the user then releases the mouse button (while
  646.          the mouse cursor is not over the menu surface), a special ID DriftID is
  647.          returned by Activate. DriftID is declared as a constant in the totMENU
  648.          unit. To recap, if the ID 0 is returned, the user escaped, and if
  649.          DriftID is returned, the user drifted off the menu and selected no
  650.          item. All other values indicate that the user chose a specific item
  651.          from the menu.
  652.  
  653.          In addition to the inherited methods, LotusMenuOBJ objects support the
  654.          following methods:
  655.  
  656.          SetSpecialKey(HK:word; ID:word);
  657.  
  658.          The hotkeys which are defined for each menu item allow the user to
  659.          select the item by pressing the appropriate hotkey. However, only the
  660.          hotkeys for the currently displayed menu are recognized. In a nested
  661.          menu system, the SetSpecialKey method can be used to define hotkeys
  662.          which will be recognized regardless of which menu level is being dis-
  663.          played. The method is passed two parameters; the keycode of the hotkey
  664.          and the ID which will be returned when the user presses this special
  665.          key. Special hotkeys can be added in any order, and they do not have to
  666.          correspond to any of the actual menu items. For example, you could add
  667.          an [KEYCAP] key to return the value of 1000 with the following state-
  668.          ment:
  669.  
  670.                   SetSpecialKey(301,1000);
  671.  
  672.          If the menu is active, and the user presses [KEYCAP], the menu will
  673.          immediately end and return a value of 1000.
  674.  
  675.          Menukey(K:word; X,Y: byte): boolean;
  676.  
  677.          This method is passed three parameters defining the details of a key-
  678.          press, i.e. the keycode, and the (X,Y) coordinate of the mouse when the
  679.          key was pressed. The function method returns TRUE if the key's details
  680.          are recognized by the menu, i.e. if the details represent a menu
  681.          hotkey, or a mouse click on the menu surface.
  682.  
  683.          Push(K:word; X,Y: byte);
  684.  
  685.          The Activate method is used to start the menu and wait for user input.
  686.          The Push method is similar to activate, except that the procedure is
  687.          passed the key details for the first input to be processed. This method
  688.          can be used in conjunction with MenuKey to test for a menu key and then
  689.  
  690.  
  691.  
  692. 12-14                                                               User's Guide
  693. --------------------------------------------------------------------------------
  694.  
  695.          process it. For example, the following code fragment prompts the user
  696.          for input. If it is related to the menu, the menu is invoked, otherwise
  697.          SomeOtherTask is called:
  698.  
  699.          var
  700.            Lmenu: LotusMenuOBJ;
  701.            K: word;
  702.            X,Y: byte;
  703.            Choice: word;
  704.            procedure SetUpLMenu;
  705.            {}
  706.            begin
  707.             with Lmenu do
  708.             begin
  709.                Init;
  710.                {...}
  711.                end;
  712.            end;
  713.  
  714.            procedure SomeOtherTask(K:word;X,Y:byte);
  715.            {}
  716.            begin
  717.               {...}
  718.            end; {SomeOtherTask)}
  719.          begin
  720.             Screen.Clear(white,'░'); {paint the screen}
  721.             SetUpLmenu;
  722.             Choice := 0;
  723.             Lmenu.Draw;
  724.             Mouse.Show;
  725.             Repeat
  726.                K := Key.Getkey;
  727.                X := Key.LastX;
  728.                Y := Key.LastY;
  729.                if Lmenu.Menukey(K,X,Y) then
  730.                   Choice := Lmenu.Push(K,X,Y)
  731.                else
  732.                   SomeOtherTask(K,X,Y);
  733.             Until (Choice <> 0) and (Choice <> DriftID);
  734.             Mouse.Hide;
  735.             writeln(Choice);
  736.          end.
  737.  
  738.  
  739.          Lotus menus can be nested many levels deep. Listed below is the demo
  740.          file DEMMN5.PAS, which shows how to create nested menus. Figure 12.5
  741.          shows the resultant display.
  742.  
  743.  
  744.  
  745. Menus Menus Menus                                                          12-15
  746. --------------------------------------------------------------------------------
  747.  
  748.          program DemoMenuFive;
  749.          {DEMMN5 - a nested Lotus menu}
  750.  
  751.          USES  DOS, CRT,
  752.                totMENU, totFAST;
  753.          var
  754.            Main,
  755.            Worksheet,
  756.            Range: LotusMenuOBJ;
  757.            Choice: word;
  758.  
  759.          procedure Pretend;
  760.          begin
  761.             Screen.Clear(31,' '); {paint the screen}
  762.             Screen.WriteAt(1,4,48,replicate(80,' '));
  763.             Screen.WriteCenter(4,48,'Not 1-2-3!');
  764.             Screen.PartClear(1,5,4,25,48,' ');
  765.          end; {Pretend}
  766.          begin
  767.             Pretend;
  768.             with Worksheet do
  769.             begin
  770.                Init;
  771.                AddFullItem('~G~lobal',100,71,'Global stuff',nil);
  772.                AddFullItem('~I~nsert',101,73,'Insert stuff',nil);
  773.                AddFullItem('~D~elete',102,68,'Delete stuff',nil);
  774.                AddFullItem('~C~olumn',103,67,'Column stuff',nil);
  775.                AddFullItem('~E~rase',104,69,'Erase stuff',nil);
  776.                AddFullItem('~T~itles',105,84,'Titles stuff',nil);
  777.                AddFullItem('~W~indow',106,87,'Window stuff',nil);
  778.                AddFullItem('~S~tatus',107,83,'Status stuff',nil);
  779.                AddFullItem('~P~age',108,80,'Page stuff',nil);
  780.                AddFullItem('~H~ide',109,72,'Hide things',nil);
  781.                SetActiveItem(1);
  782.                SetGap(1);
  783.             end;
  784.             with Range do
  785.             begin
  786.                Init;
  787.                AddFullItem('~F~ormat',200,70,'Format stuff',nil);
  788.                AddFullItem('~L~abel',201,76,'Label stuff',nil);
  789.                AddFullItem('~E~rase',202,69,'Erase stuff',nil);
  790.                AddFullItem('~N~ame',203,78,'Name stuff',nil);
  791.                AddFullItem('~J~ustify',204,74,'Justify stuff',nil);
  792.                AddFullItem('~P~rot',205,80,'Protect stuff',nil);
  793.                AddFullItem('~U~nprot',206,85,'Unprotect stuff',nil);
  794.                AddFullItem('~I~nput',207,73,'Input stuff',nil);
  795.                AddFullItem('~V~alue',208,86,'Value stuff',nil);
  796.  
  797.  
  798.  
  799. 12-16                                                               User's Guide
  800. --------------------------------------------------------------------------------
  801.  
  802.                AddFullItem('~T~rans',209,84,'Transpose stuff',nil);
  803.                AddFullItem('~S~earch',209,83,'Search for things',nil);
  804.                SetActiveItem(1);
  805.                SetGap(1);
  806.             end;
  807.             with Main do
  808.             begin
  809.                Init;
  810.                AddFullItem('~W~orksheet',1,87,
  811.                            'Worksheet and global operations',@Worksheet);
  812.                AddFullItem('~R~ange',2,82,
  813.                            'Commands for manipulating data ranges',@Range);
  814.                AddFullItem('~C~opy',3,67,
  815.                            'Cell and range copying commands',nil);
  816.                AddFullItem('~M~ove',4,77,'Cell and range moving commands',nil);
  817.                AddFullItem('~F~ile',5,70,'File loading and saving operation-
  818.          s',nil);
  819.                AddFullItem('~P~rint',6,80,'Graph and spreadsheet printing',nil);
  820.                AddFullItem('~G~raph',7,71,'Spreadsheet charting',nil);
  821.                AddFullItem('~D~ata',8,68,'Database operations',nil);
  822.                AddFullItem('~S~ystem',9,83,'Drop to the Operating System',nil);
  823.                AddFullItem('~Q~uit',99,81,'Miller Time!',nil);
  824.                SetActiveItem(1);
  825.                SetGap(1);
  826.                Choice := Activate;
  827.                Done;
  828.                Worksheet.Done;
  829.                Range.Done;
  830.             end;
  831.             gotoxy(1,5);
  832.             if Choice = 0 then
  833.                Writeln('You escaped')
  834.             else
  835.                Writeln('You selected menu item ',Choice);
  836.          end.
  837.  
  838.  
  839.  
  840. Figure 12.5                                                             [SCREEN]
  841. Nested Lotus
  842. Menus
  843.  
  844.  
  845.  
  846. Pull Down Menus
  847.          The totMENU unit provides a number of objects to help you create pull-
  848.          down menus like the one used in the Turbo Pascal integrated environ-
  849.          ment. The main pull-down menu object is PullMenuOBJ, and it is a
  850.  
  851.  
  852.  
  853. Menus Menus Menus                                                          12-17
  854. --------------------------------------------------------------------------------
  855.  
  856.          descendant of LotusMenuOBJ -- a pull-down menu is really a Lotus menu
  857.          which calls pop-up menus when an item is selected from the main menu
  858.          bar. The other pull-down menus are EZPullArrayOBJ and EZPullLinkOBJ,
  859.          which allow you to quickly create a pull-down menu based on the con-
  860.          tents of a string array or linked list, respectively. Hence the prefix,
  861.          EZ!
  862.  
  863.  
  864. PullMenuOBJ
  865.  
  866.          99% of Toolkit users will use the EZ objects, but before moving on to
  867.          explain such shortcuts, the PullMenuOBJ object needs to be described in
  868.          detail.
  869.          PullMenuOBJ supports the following, previously described, methods:
  870.  
  871.          Init;
  872.          AddItem(Txt:StrVisible);
  873.          SetHK(Item:byte; HK:word);
  874.          SetMessage(Item:byte; Msg:StrVisible);
  875.          SetID(Item:byte; ID:word);
  876.          SetStatus(Item:byte, On:boolean);
  877.          SetSubMenu(Item:byte; SubMenu:BaseMenuPtr);
  878.          AddFullItem(Txt:StrVisible;ID,Hk:word; Msg:StrVisible; SubM:Baseme-
  879.          nuPtr);
  880.          Draw;
  881.          Activate: word;
  882.          Remove;
  883.          SetGap(G:byte);
  884.          SetMenuXY(X,Y: byte);
  885.          SetMessageXY(X,Y:byte);
  886.          SetAllowEsc(On:boolean);
  887.          SetActiveItem(Item:byte);
  888.          SetColors(HiHot,HoNorm,LoHot,LoNorm,Off:byte);
  889.          SetSpecialKey(HK:word; ID:word);
  890.          Menukey(K:word; X,Y: byte): boolean;
  891.          Push(K:word; X,Y: byte);
  892.          Done;
  893.  
  894.          To build a pull-down menu using PullMenuOBJ, you create an object of
  895.          type PullMenuOBJ, and one MenuOBJ object for each pull-down menu panel.
  896.          When you add the items to PullMenuOBJ, the sub-menu parameter should be
  897.          a pointer to the appropriate MenuOBJ instance. Listed below is the demo
  898.          program DEMMN6.PAS, followed by figure 12.6 showing the display.
  899.  
  900.          program DemoMenuSix;
  901.          {DEMMN6 - a simple pullmenu}
  902.          USES  DOS, CRT,
  903.                totMENU, totFAST;
  904.  
  905.  
  906.  
  907. 12-18                                                               User's Guide
  908. --------------------------------------------------------------------------------
  909.  
  910.          var
  911.            Fmenu,
  912.            Emenu: MenuOBJ;
  913.            Pmenu: PullMenuOBJ;
  914.            Choice: word;
  915.  
  916.          procedure InitSubmenus;
  917.          {}
  918.          begin
  919.             with Fmenu do
  920.             begin
  921.                Init;
  922.                AddFullItem(' ~O~pen...       ',101,79,'',nil);
  923.                AddFullItem(' ~N~ew           ',102,78,'',nil);
  924.                AddFullItem(' ~S~ave...       ',103,83,'',nil);
  925.                AddFullItem(' S~a~ve as       ',104,65,'',nil);
  926.                AddFullItem(' Save a~l~l      ',105,79,'',nil);
  927.                AddItem('-');
  928.                AddFullItem(' ~C~hange dir ...',106,67,'',nil);
  929.                AddFullItem(' ~P~rint         ',107,80,'',nil);
  930.                AddFullItem(' ~G~et info...   ',108,71,'',nil);
  931.                AddFullItem(' ~D~OS shell     ',109,68,'',nil);
  932.                AddFullItem(' E~x~it          ',110,88,'',nil);
  933.                SetForPull;
  934.             end;
  935.             with Emenu do
  936.             begin
  937.                Init;
  938.                AddFullItem(' ~R~estore line   ',201,82,'',nil);
  939.                AddItem('-');
  940.                AddFullItem(' Cu~t~            ',202,84,'',nil);
  941.                AddFullItem(' ~C~opy           ',203,67,'',nil);
  942.                AddFullItem(' ~P~aste          ',204,80,'',nil);
  943.                AddFullItem(' Copy ~E~xample   ',205,69,'',nil);
  944.                SetStatus(6,false);
  945.                AddFullItem(' ~S~how clipboard ',206,83,'',nil);
  946.                AddItem('-');
  947.                AddFullItem(' C~l~ear          ',207,76,'',nil);
  948.                SetForPull;
  949.             end;
  950.          end; {InitSubMenus}
  951.          begin
  952.             Screen.Clear(white,'░'); {paint the screen}
  953.             Screen.PartClear(1,1,80,1,31,' ');
  954.             InitSubMenus;
  955.             with Pmenu do
  956.             begin
  957.                Init;
  958.  
  959.  
  960.  
  961. Menus Menus Menus                                                          12-19
  962. --------------------------------------------------------------------------------
  963.  
  964.                AddFullItem('   ~F~ile   ',1,70,'',@Fmenu);
  965.                AddFullItem('   ~E~dit   ',2,69,'',@Emenu);
  966.                AddFullItem('   ~R~un    ',3,82,'',nil);
  967.                SetID(3,3);
  968.                Choice := Activate;
  969.                Done;
  970.             end;
  971.             GotoXY(25,15);
  972.             if Choice = 0 then
  973.                Writeln('You escaped')
  974.             else
  975.                Writeln('You selected menu item ',Choice);
  976.          end.
  977.  
  978.  
  979.  
  980. Figure 12.6                                                             [SCREEN]
  981. A Simple Pull-down
  982. Menu
  983.  
  984.  
  985.          The demo program creates a pull-down menu with three elements on the
  986.          menu bar: File, Edit and Run. A sub-menu is displayed when either of
  987.          the first two items is selected. The program therefore requires three
  988.          menu objects: a PullMenuOBJ to define the main menu bar, and two
  989.          MenuOBJ objects to define the pull-down elements. Notice the method
  990.          call SetForPull in both the MenuOBJ set-up routines. This method sets
  991.          the characteristics of the MenuOBJ objects to fit in a pull-down menu
  992.          environment, e.g. the border is set to 1, any titles are removed, etc.
  993.  
  994.          Also, notice that each selectable item is assigned a unique ID. When
  995.          the user chooses an Item (which doesn't call a sub-menu), the item ID
  996.          is returned by the method Activate or Push.
  997.          If you want to add more sub-sub-menus, simply create additional MenuOBJ
  998.          objects, and set a menu item to point to the sub-menu instance. For
  999.          example, the following code fragment will result in a sub-menu being
  1000.          displayed when the Print option is selected from the file menu (it is
  1001.          assumed that PrintMenu is an instance of MenuOBJ):
  1002.  
  1003.                AddFullItem(' ~P~rint         ',106,80,'',@PrintMenu);
  1004.          As demonstrated by the third item "Run", items on the main menu bar do
  1005.          not have to call sub-menus. If the user selects Run from the main menu,
  1006.          an ID of three is returned.
  1007.  
  1008.  
  1009.  
  1010. 12-20                                                               User's Guide
  1011. --------------------------------------------------------------------------------
  1012.  
  1013. EZ Pull-Down Menus
  1014.  
  1015.          The objects EZPullArrayOBJ and EZPullLinkOBJ provide a quick and easy
  1016.          way of building powerful pull-down menus. The basic principle of the EZ
  1017.          objects is that you define all the components of each menu item in a
  1018.          string, and then instruct the Toolkit to build a pull-down menu from
  1019.          the strings. The strings can either be stored in an array or in a
  1020.          linked list.
  1021.          Each string can have between one and four elements, with each element
  1022.          being separated by a double-quote ("). The first element is the menu
  1023.          item text, the second element is the message or menu description, the
  1024.          third element is the item ID, and the fourth element is an optional
  1025.          special hotkey which can be pressed anywhere in the menu hierarchy to
  1026.          select the item. The syntax of the string is as follows:
  1027.  
  1028.                      'menu text"description"ID"SpecialHK'
  1029.          For example, the following string declares the menu item "Open..." :
  1030.  
  1031.          ' ~O~pen...       "Locate and open a file in an edit window"201"316'
  1032.          You do not need to specify all four elements. For example, if the item
  1033.          does not have a special hotkey, omit the fourth part. If the item text
  1034.          includes a highlighted character, e.g. ~O~, the Toolkit will automati-
  1035.          cally assign that letter as the standard item hotkey.
  1036.  
  1037.          The strings in the array or list must be specified in the order that
  1038.          the picks will appear in the menu, and strings representing a main menu
  1039.          item must begin with the backslash character. If you want a topic to be
  1040.          non-selectable, start the string with an underscore, '_'. For example,
  1041.          the following strings could be used to create a menu similar to the
  1042.          DEMMN6.PAS program described earlier:
  1043.           '\ ~F~ile   ';
  1044.           ' ~O~pen...       "101'
  1045.           ' ~N~ew           "102'
  1046.           ' ~S~ave...       "103'
  1047.           ' S~a~ve as       "104'
  1048.           ' Save a~l~l      "105'
  1049.           '-'
  1050.           ' ~C~hange dir ..."106'
  1051.           ' ~P~rint         "107'
  1052.           ' ~G~et info...   "108'
  1053.           ' ~D~OS shell     "109'
  1054.           ' E~x~it          "110'
  1055.           '\  ~E~dit   '
  1056.           ' ~R~estore line  "201'
  1057.           '-'
  1058.           ' Cu~t~           "202'
  1059.           ' ~C~opy          "203'
  1060.           ' ~P~aste         "204'
  1061.  
  1062.  
  1063.  
  1064. Menus Menus Menus                                                          12-21
  1065. --------------------------------------------------------------------------------
  1066.  
  1067.           '_Copy ~E~xample   "205'
  1068.           ' ~S~how clipboard "206'
  1069.           '-'
  1070.           ' C~l~ear          "207'
  1071.           '\  ~R~un    "3'
  1072.  
  1073.  
  1074.  
  1075.            Note: the EZ objects can only be used to create a single-level
  1076.            pull-down menu. Refer to the section Adding Sub-Menus to see how
  1077.            to customize an EZ pull-down menu with sub-menus.
  1078.  
  1079.          The EZ pull object dynamically creates an instance of PullMenuOBJ, and
  1080.          as many MenuOBJ instances as needed to create the menu. The EZ pull
  1081.          objects include the following two function methods which allow you to
  1082.          directly access the internal PullMenuOBJ and MenuOBJ instances:
  1083.  
  1084.  
  1085.          MainMenu: PullMenuPtr;
  1086.          This function returns a pointer to the PullMenuOBJ instance used by the
  1087.          EZ object. You may change the characteristics settings of the instance
  1088.          by using the syntax Mainmenu^.method. For example, the following method
  1089.          will draw the main menu bar: Mainmenu^.Draw.
  1090.  
  1091.  
  1092.          SubMenu(MenuNumber: byte): SubMenuPtr;
  1093.          This function returns a pointer to one of the MenuOBJ instances, i.e.
  1094.          one of the first-level menu panels. You may change the characteristics
  1095.          of the instance by using the syntax Submenu(num)^.method.
  1096.  
  1097.  
  1098. EZPullArrayOBJ
  1099.  
  1100.          The EZPullArrayOBJ builds and displays a pull-down menu based on the
  1101.          contents of a string array. After calling Init, the following method
  1102.          should be called to pass the menu details to the object:
  1103.  
  1104.          AssignList(var StrArray; Total:longint; StrLength:byte);
  1105.  
  1106.          AssignList identifies the string array which contains the menu struc-
  1107.          ture. The method is passed three parameters; the string array, the
  1108.          total number of elements in the array, and the defined string length of
  1109.          each array element.
  1110.  
  1111.          Unlike other Toolkit objects such as List and Browse, the EZPullArray-
  1112.          OBJ copies the data from the string array. This means that, after
  1113.          assignment, you can dispose of the string array. The partial listing of
  1114.  
  1115.  
  1116.  
  1117.  
  1118. 12-22                                                               User's Guide
  1119. --------------------------------------------------------------------------------
  1120.  
  1121.          the demo file DEMMN7.PAS (listed below), illustrates this technique.
  1122.          The string array is created locally in the procedure CreateMenu, and is
  1123.          automatically disposed of when the CreateMenu procedure finishes.
  1124.  
  1125.          The demo program is a mock-up of Turbo Pascal's own IDE menu (see
  1126.          Figure 12.7)
  1127.          program DemoMenuSeven;
  1128.          {DEMMN7 - using EZPull objects}
  1129.          USES  DOS, CRT,
  1130.                totMENU, totFAST;
  1131.  
  1132.          var
  1133.            Menu: EZPullArrayOBJ;
  1134.            Choice: word;
  1135.          procedure CreateMenu;
  1136.          {}
  1137.          var
  1138.            Mtxt: Array[1..84] of string[90];
  1139.          begin
  1140.             MTxt[1] := '\ p "System Commands';
  1141.             MTxt[2] := ' ~A~bout...  "Show version and copyright information-
  1142.          "100';
  1143.             MTxt[3] := ' ~R~efresh display "Redraw the screen"101';
  1144.             MTxt[4] := ' ~C~lear desktop   "Close all windows on the desktop,
  1145.          clear history lists"102';
  1146.             MTxt[5] := '\ ~F~ile "File management commands (Open, New, Save,
  1147.          etc.)';
  1148.             MTxt[6] := ' ~O~pen...       "Locate and open a file in an edit
  1149.          window"201';
  1150.             {...}
  1151.             MTxt[84] := ' ~H~elp on Help   "How to use online Help"1005';
  1152.             with Menu do
  1153.             begin
  1154.                Init;
  1155.                AssignList(MTxt,84,90);
  1156.             end;
  1157.          end; {CreateMenu}
  1158.  
  1159.          begin
  1160.             Screen.PartClear(1,2,80,24,white,'░'); {paint the screen}
  1161.             Screen.PartClear(1,1,80,1,31,' ');
  1162.             Screen.PartClear(1,25,80,25,31,' ');
  1163.             Screen.WritePlain(9,25,'│');
  1164.             CreateMenu;
  1165.             with Menu do
  1166.             begin
  1167.                Choice := Push(13,0,0);   {Pass Enter to make menu pull down}
  1168.                Done;
  1169.             end;
  1170.  
  1171.  
  1172. Menus Menus Menus                                                          12-23
  1173. --------------------------------------------------------------------------------
  1174.  
  1175.             GotoXY(25,15);
  1176.             if Choice = 0 then
  1177.                Writeln('You escaped')
  1178.             else
  1179.                Writeln('You selected menu item ',Choice);
  1180.          end.
  1181.  
  1182.  
  1183. Figure 12.7                                                             [SCREEN]
  1184. An EZ Pull-down
  1185. Menu
  1186.  
  1187.  
  1188.  
  1189. EZPullLinkOBJ
  1190.          The EZPullLinkOBJ reads the menu definition from a linked list, i.e.
  1191.          from an instance of DLLOBJ or one of its descendants. After calling
  1192.          Init, the following method should be called to pass the menu details to
  1193.          the object:
  1194.  
  1195.  
  1196.          AssignList(var LinkList DLLOBJ);
  1197.          AssignList identifies the linked list which contains the menu defini-
  1198.          tion. The method is passed one parameter; an instance of DLLOBJ or a
  1199.          descendant, e.g. StrDLLOBJ.
  1200.  
  1201.  
  1202.          As with EZPullArrayOBJ, the data is copied from the linked list to the
  1203.          internal menu objects. Listed below is the demo program DEMMN8.PAS,
  1204.          which shows how EZPullLinkOBJ can be used to read a menu from disk.
  1205.          program DemoMenuEight;
  1206.          {DEMMN8 - reading a menu from disk}
  1207.          USES  DOS, CRT,
  1208.                totMENU, totFAST, totLINK;
  1209.  
  1210.          var
  1211.            Menu: EZPullLinkOBJ;
  1212.            Choice: word;
  1213.          procedure CreateMenu;
  1214.          {}
  1215.          var
  1216.            FileList: StrDLLOBJ;
  1217.            Retcode: integer;
  1218.            F: text;
  1219.            Line:string;
  1220.          begin
  1221.             assign(F,'DEMMN8.TXT');
  1222.             {$I-}
  1223.  
  1224.  
  1225.  
  1226.  
  1227. 12-24                                                               User's Guide
  1228. --------------------------------------------------------------------------------
  1229.  
  1230.             reset(F);
  1231.             {$I+}
  1232.             if ioresult <> 0 then
  1233.             begin
  1234.                Writeln('Error: the file DEMMN8.TXT must be in the default
  1235.          directory!');
  1236.                halt(1);
  1237.             end;
  1238.             with FileList do
  1239.             begin
  1240.                Init;
  1241.                Retcode := 0;
  1242.                ReadLn(F,Line);
  1243.                while not eof(F) and (Retcode = 0) do
  1244.                begin
  1245.                   Readln(F,Line);
  1246.                   Retcode := Add(Line);
  1247.                end;
  1248.                close(F);
  1249.             end;
  1250.             with Menu do
  1251.             begin
  1252.                Init;
  1253.                AssignList(FileList);
  1254.                FileList.Done;
  1255.             end;
  1256.          end; {CreateMenu}
  1257.  
  1258.          begin
  1259.             Screen.PartClear(1,2,80,24,white,'░'); {paint the screen}
  1260.             Screen.PartClear(1,1,80,1,31,' ');
  1261.             Screen.PartClear(1,25,80,25,31,' ');
  1262.             Screen.WritePlain(9,25,'│');
  1263.             CreateMenu;
  1264.             with Menu do
  1265.             begin
  1266.                Choice := Push(13,0,0);   {Pass Enter to make menu pull down}
  1267.                Done;
  1268.             end;
  1269.             GotoXY(25,15);
  1270.             if Choice = 0 then
  1271.                Writeln('You escaped')
  1272.             else
  1273.                Writeln('You selected menu item ',Choice);
  1274.          end.
  1275.  
  1276.  
  1277.  
  1278. Menus Menus Menus                                                          12-25
  1279. --------------------------------------------------------------------------------
  1280.  
  1281. Adding Sub-Menus
  1282.  
  1283.          The EZ objects provide a quick way of building a single level pull-down
  1284.          menu. If you want to have some sub-menus, you can still use the EZ
  1285.          objects. First call the AssignList method to create the main pull-down
  1286.          menu objects, and then create as many MenuOBJ instances as needed.
  1287.          Finally, use the SubMenu function method to access individual menu ele-
  1288.          ments and assign your own MenuOBJ instances to the appropriate menu
  1289.          item.
  1290.          Listed below is an extract of the demo file DEMMN9.PAS, which illus-
  1291.          trates this technique:
  1292.  
  1293.          program DemoMenuNine;
  1294.          {DEMMN9 - using a EZPull object with sub menus and hotkeys}
  1295.          USES  DOS, CRT,
  1296.                totMENU, totFAST;
  1297.          var
  1298.            Env,Watch: MenuOBJ;
  1299.            Menu: EZPullArrayOBJ;
  1300.            Choice: word;
  1301.  
  1302.          procedure CreateSubMenus;
  1303.          {}
  1304.          begin
  1305.             with Env do
  1306.             begin
  1307.                Init;
  1308.                SetForPull;
  1309.                AddFullItem(' ~P~references... ',8061,80,
  1310.                            'Specify desktop settings',nil);
  1311.                AddFullItem(' ~E~ditor...      ',8062,69,
  1312.                            'Specify editor settings',nil);
  1313.                AddFullItem(' ~M~ouse...       ',8063,77,
  1314.                            'Specify mouse settings',nil);
  1315.                AddFullItem(' ~S~tartup...     ',8064,83,
  1316.                            'Permanently change default startup options',nil);
  1317.                AddFullItem(' ~C~olors...      ',8065,67,
  1318.                            'Customize IDE colors for windows, menus, etc.',nil);
  1319.             end;
  1320.             with Watch do
  1321.             begin
  1322.                Init;
  1323.                SetForPull;
  1324.                AddFullItem(' ~A~dd watch...       ',7021,65,
  1325.                    'Insert a watch expression into the Watch window',nil);
  1326.                AddFullItem(' ~D~elete watch       ',7022,68,
  1327.                    'Remove the current watch expression from the Watch window',-
  1328.          nil);
  1329.                AddFullItem(' ~E~dit watch...      ',7023,69,
  1330.  
  1331.  
  1332. 12-26                                                               User's Guide
  1333. --------------------------------------------------------------------------------
  1334.  
  1335.                    'Edit the current watch expression in the Watch window',nil);
  1336.                AddFullItem(' ~R~emove all watches ',7024,82,
  1337.                    'Delete all watch expressions from the Watch window',nil);
  1338.             end;
  1339.          end; {CreateSubMenus}
  1340.  
  1341.          procedure CreateMenu;
  1342.          {}
  1343.          var
  1344.            Mtxt: Array[1..84] of string[100];
  1345.          begin
  1346.             MTxt[1] := '\ p "System Commands';
  1347.             {...}
  1348.             MTxt[84] := ' ~H~elp on Help       "How to use online Help"1005';
  1349.             with Menu do
  1350.             begin
  1351.                Init;
  1352.                AssignList(MTxt,84,100);
  1353.             end;
  1354.          end; {CreateMenu}
  1355.          begin
  1356.             Screen.PartClear(1,2,80,24,white,'░'); {paint the screen}
  1357.             Screen.PartClear(1,1,80,1,31,' ');
  1358.             Screen.PartClear(1,25,80,25,31,' ');
  1359.             Screen.WritePlain(9,25,'│');
  1360.             CreateMenu;
  1361.             CreateSubMenus;
  1362.             with Menu do
  1363.             begin
  1364.                SubMenu(7)^.SetSubMenu(2,@Watch);
  1365.                SubMenu(8)^.SetSubMenu(7,@Env);
  1366.                Choice := Activate
  1367.                Done;
  1368.                Env.Done;
  1369.                Watch.Done;
  1370.             end;
  1371.             GotoXY(25,15);
  1372.             if Choice = 0 then
  1373.                Writeln('You escaped')
  1374.             else
  1375.                Writeln('You selected menu item ',Choice);
  1376.          end.
  1377.  
  1378.  
  1379. Figure 12.8                                                             [SCREEN]
  1380. Nested Pull-down
  1381. Menus
  1382.  
  1383.  
  1384.  
  1385. Menus Menus Menus                                                          12-27
  1386. --------------------------------------------------------------------------------
  1387.  
  1388. Adding Help
  1389.  
  1390.          Adding help to menu objects is very similar to the ways described for
  1391.          other objects like DirWinOBJ. To add a help facility to any menu
  1392.          object, all you have to do is create a procedure following some spe-
  1393.          cific rules, and then call the menu method SetHelpHook to instruct the
  1394.          Toolkit to use your procedure.
  1395.          For a procedure to be eligible as a help hook, it must adhere to the
  1396.          following rules:
  1397.  
  1398.          Rule 1     The procedure must be declared as a FAR procedure. This can
  1399.                     be achieved by preceding the procedure with a {$F+} compiler
  1400.                     directive, and following the procedure with a {$F-} direc-
  1401.                     tive. Alternatively, Turbo 6 users can use the new keyword
  1402.                     FAR following the procedure statement.
  1403.          Rule 2     The procedure must be declared with one passed parameter of
  1404.                     type word. This parameter indicates the ID of the high-
  1405.                     lighted item at the time the user requested help.
  1406.  
  1407.          Rule 3     The procedure must be at the root level, i.e. the procedure
  1408.                     cannot be nested within another procedure.
  1409.          The following procedure declaration follows these rules:
  1410.  
  1411.                   {$F+}
  1412.                   procedure MyHelpHook(ID:word);
  1413.                   .....{procedure statements}
  1414.                   end;
  1415.                   {$F-}
  1416.  
  1417.          The following method SetHelpHook is then called to instruct the Toolkit
  1418.          to call your procedure when the user asks for help:
  1419.  
  1420.  
  1421.          SetHelpHook(PassedProc:HelpProc);
  1422.          This method is passed the procedure name of a procedure declared using
  1423.          the rules outlined above.
  1424.  
  1425.  
  1426.          Remember that if you are using an EZ object, you must access the Pull-
  1427.          MenuOBJ using the following statement:
  1428.                   Mainmenu^.SetHelpHook(YourProc);
  1429.  
  1430.